/*************************************************************************
    > File Name: ./include/gtest.h
    > Author: 闫海潮 
    > Mail: 983628315@qq.com 
    > Created Time: Sat 07 Nov 2020 08:07:14 PM CST
 ************************************************************************/
#ifndef GTEST_H
#define GTEST_H

#include <linklist.h>
#define COLOR(a, b) "\033["#b"m"#a"\033[0m"
#define COLOR_HL(a, b) "\033[1;"#b"m"#a"\033[0m"

#define GREEN(a) COLOR(a, 32)
#define GREEN_HL(a) COLOR_HL(a, 32)
#define YELLOW(a) COLOR(a, 33)
#define YELLOW_HL(a) COLOR_HL(a, 33)
#define RED(a) COLOR(a, 31)
#define RED_HL(a) COLOR_HL(a, 31)
#define BLUE(a) COLOR(a, 34)
#define BLUE_HL(a) COLOR_HL(a, 34)
#define D_GREEN(a) COLOR(a, 36)
#define D_GREEN_HL(a) COLOR_HL(a, 36)       

#define Type(a) _Generic(\
        (a),\
        int: "%d",\
        char: "%c",\
        double: "%lf",\
        float: "%f",\
        char *: "%s",\
        const char *: "%s",\
        long int: "%ld",\
        long long: "%lld"\
        )

#define PP(a, color) {\
    char frm[200] = {0};\
    sprintf(frm, color(" %s "), Type(a));\
    printf(frm, (a));\
}

#define TEST(a, b)\
void a##ceshi##b ();\
__attribute__((constructor))\
void ceshi_##a##ceshi##b () {\
    add_function(a##ceshi##b, #a "." #b);\
} \
void a##ceshi##b()

#define EXPECT(a, b, c) {\
        __typeof(a) a_ = (a);\
        __typeof(b) b_ = (b);\
if ((a_) c (b_)) \
++info.success;\
else {\
    ++info.total;\
      printf(YELLOW_HL(\n\t\t%s: %d: failure\n\
                  \t\t\texpect: a c b\n\
                  \t\t\tactual:  ), __FILE__, __LINE__);\
    PP(a_, YELLOW_HL);\
    printf(YELLOW_HL(vs));\
    PP(b_, YELLOW_HL);\
    printf("\n\n");\
}\
printf("[-----------]   " #a #c #b "   %s\n", ((a_) c (b_) ? GREEN_HL( TRUE) :RED_HL( FALSE)));\
                        }

#define EXPECT_EQ(a, b) EXPECT(a, b, ==)
#define EXPECT_NE(a, b) EXPECT(a, b, !=)
#define EXPECT_LT(a, b) EXPECT(a, b, <)
#define EXPECT_LE(a, b) EXPECT(a, b, <=)
#define EXPECT_GT(a, b) EXPECT(a, b, >)
#define EXPECT_GE(a, b) EXPECT(a, b, >=)

int RUN_ALL_TESTS();

typedef void (*fun)();

typedef struct Add_fun {
    char * name;
    fun fun_name;
    struct Link_node p;
} Add_fun;

struct fun_info {
    long long int total, success;
};
void add_function(fun, const char*);
extern struct fun_info info;
#endif
